package cn.idongjia.live.vcload;

import cn.idongjia.live.exception.LiveException;
import cn.idongjia.live.pojo.LVSChannel;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Date;
import java.util.Random;

/**
 * 网易云服务端API封装
 * Created by wuqiang on 16/4/1.
 */
public class VCloudClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(VCloudClient.class);

    private static final String CREATE_CHANNEL_URL = "https://vcloud.163.com/app/channel/create";
    private static final String UPDATE_CHANNEL_URL = "https://vcloud.163.com/app/channel/update";
    private static final String DELETE_CHANNEL_URL = "https://vcloud.163.com/app/channel/delete";
    private static final String LIST_CHANNEL_URL = "https://vcloud.163.com/app/channellist";
    private static final String STATUS_CHANNEL_URL = "https://vcloud.163.com/app/channelstats";
    private static final String ADDRESS_CHANNEL_URL = "https://vcloud.163.com/app/address";
    private static final String PAUSE_CHANNEL_URL = "https://vcloud.163.com/app/channel/pause";
    private static final String RESUME_CHANNEL_URL = "https://vcloud.163.com/app/channel/resume";

    private static final long THOUSAND = 1000L;
    private CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    /**
     * 生成1000以内的随机数
     * 创建频道所需参数
     *
     * @return 随机生成1000以内的数字, 网易云所需, 暂时不知道何用
     */
    private String createNonce() {
        Random r = new Random();
        return "" + r.nextInt((int) THOUSAND);
    }

    private void setHead(final HttpPost httpPost) {
        String nonce = createNonce();
        String curTime = String.valueOf((new Date()).getTime() / THOUSAND);
        String checkSum =
                CheckSumBuilder.getCheckSum(VCloudCount.APP_SECRET, nonce, curTime);
        // 设置请求的header
        httpPost.addHeader("APPKEY", VCloudCount.APP_KEY);
        httpPost.addHeader("Nonce", nonce);
        httpPost.addHeader("CurTime", curTime);
        httpPost.addHeader("CheckSum", checkSum);
        httpPost.addHeader("Content-Type", "application/json;charset=utf-8");
    }

    private HttpPost createPost(final String json, final String url) {
        HttpEntity httpEntity = new StringEntity(json, "utf-8");
        HttpPost httpPost = new HttpPost(url);
        setHead(httpPost);
        httpPost.setEntity(httpEntity);
        return httpPost;
    }

    /**
     * 创建新增频道所需的POST类
     *
     * @param channelName 频道名称
     * @param channelType 频道类型 （0:rtmp；1:hls；2:http）
     *                    {
     *                    "code" : XXX,
     *                    "msg" : XXX,
     *                    "ret" : {
     *                    "cid" : XXX,
     *                    "ctime" : XXX,
     *                    "pushurl" : XXX,
     *                    "httpPullUrl" : XXX,
     *                    "hlsPullUrl" : XXX,
     *                    "rtmpPullUrl" : XXX
     *                    }
     *                    }
     * @return 新增频道Post类
     */
    public HttpPost createChannelPost(final String channelName, final int channelType) {
        return createPost(
                "{\"name\":\"" + channelName + "\", \"type\":" + channelType + "}",
                CREATE_CHANNEL_URL);
    }

    /**
     * 修改频道信息
     *
     * @param channelId
     * @param newName   要修改的频道名称
     * @param newType   要修改的频道类型 （0:rtmp；1:hls；2:http）
     * @return HttpPost
     */
    public HttpPost updateChannelPost(
            final String channelId, final String newName, final int newType) {
        return createPost(
                "{\"cid\":\"" + channelId + "\", \"name\":\"" + newName
                        + "\", \"type\":" + newType + "}", UPDATE_CHANNEL_URL);
    }

    /**
     * 删除频道
     *
     * @param channelId
     * @return
     */
    public HttpPost deleteChannelPost(final String channelId) {
        return createPost(
                "{\"cid\":\"" + channelId + "\"}", DELETE_CHANNEL_URL);
    }

    /**
     * params.records 单页记录数，默认值为10	否
     * params.pnum 要取第几页，默认值为1	否
     * params.ofield 排序的域，支持的排序域为：ctime（默认）	否
     * params.sort 升序还是降序，1升序，0降序，默认为desc	否
     *
     * @return
     */
    public HttpPost listChannelPost(final LVSChannel.ListParams params) {
        return createPost(params.toString(), LIST_CHANNEL_URL);
    }

    /**
     * 查询频道状态
     *
     * @param channelId 频道ID
     * @return
     */
    public HttpPost getStatusChannelPost(final String channelId) {
        return createPost(
                "{\"cid\":\"" + channelId + "\"}", STATUS_CHANNEL_URL);
    }

    /**
     * 查询频道地址
     *
     * @param channelId
     * @return 参数    类型	说明
     * code	int	错误码
     * pushUrl	String	推流地址
     * httpPullUrl	String	http拉流地址
     * hlsPullUrl	String	hls拉流地址
     * rtmpPullUrl	String	rtmp拉流地址
     * msg	String	错误信息
     */
    public HttpPost getAddressChannelPost(final String channelId) {
        return createPost(
                "{\"cid\":\"" + channelId + "\"}", ADDRESS_CHANNEL_URL);
    }

    /**
     * 暂停频道
     *
     * @param channelId
     * @return
     */
    public HttpPost pauseChannelPost(String channelId) {
        return createPost("{\"cid\":\"" + channelId + "\"}", PAUSE_CHANNEL_URL);
    }

    /**
     * 恢复频道
     *
     * @param channelId
     * @return
     */
    public HttpPost resumeChannelPost(String channelId) {
        return createPost("{\"cid\":\"" + channelId + "\"}", RESUME_CHANNEL_URL);
    }

    /**
     * 发送POST请求
     *
     * @param httpPost 请求参数
     * @return http响应结果Gson元素
     */
    public JsonObject send(final HttpPost httpPost) {
        // 执行请求
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            // 获取执行结果
            //HttpEntity httpEntity = response.getEntity();
            int statusCode = response.getStatusLine().getStatusCode();
            String httpResult = EntityUtils.toString(response.getEntity(), "utf-8");
            if (statusCode != HttpStatus.SC_OK) {
                LOGGER.debug("statusCode:{}", statusCode);
                throw new LiveException(httpResult);
            }
            JsonObject jsonObject = new JsonParser().parse(httpResult).getAsJsonObject();
            System.out.println("jsonObject:" + jsonObject);
            if (jsonObject.has(VCloudCount.KEY_CODE)
                    && jsonObject.get(VCloudCount.KEY_CODE).getAsInt()
                    == VCloudCount.SUCCESS_CODE) {
                if (jsonObject.has(VCloudCount.KEY_RESULT)) {
                    return jsonObject.get(VCloudCount.KEY_RESULT).getAsJsonObject();
                } else {
                    return jsonObject;
                }
            } else {
                throw new LiveException("网易云API访问错误:" + jsonObject.get(VCloudCount.KEY_MSG));

            }
        } catch (IOException e) {
            LOGGER.error("调用网易云服务端接口异常!", e);
            throw new LiveException(e.getMessage());
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                LOGGER.error("调用网易云服务端接口异常!", e);
                throw new LiveException(e.getMessage());
            }
        }
    }

    public static void main(final String[] args) throws Exception {
        VCloudClient vCloudClient = new VCloudClient();
        LVSChannel.ListParams params = new LVSChannel.ListParams();
        params.setPnum(1);
        params.setOfield("ctime");
        HttpPost post =
                //vCloudClient.createChannelPost("testchannel4", 0);
                //vCloudClient.updatePost("cdd5bdc15d5148cfbe93d86863c840be", "testChannel1", 0);
                //vCloudClient.deletePost("cdd5bdc15d5148cfbe93d86863c840be");
                vCloudClient.listChannelPost(params);
        //vCloudClient.getStatusChannelPost("7beb21ca3fe541f4b868c16ac82190ac");
        //vCloudClient.getAddressChannelPost("7beb21ca3fe541f4b868c16ac82190ac");
        JsonObject o = vCloudClient.send(post);
        System.out.println(o);
    }

}
